from DDPM.Evaluation.UMap import *
import numpy as np
from DDPM.Evaluation.Control import *
import re

def start_analysis(control_params):
    print(f"##### Start analysis of {control_params['project_name']} #####")
    project_name=control_params["project_name"]
    project_path=f"{decode_result_save_path}/{project_name}"
    sample_feature_vectors = load_feature_vectors(project_path, "Samples")
    dead_feature_vectors, _, _, _ = load_feature_vectors_from_dead()

    # =========================多样性指标====================================
    # 计算 sample_feature_vectors 每个向量距离自身所有向量的最小距离，形成列表，以评估生成结果的多样性
    min_distance_list_from_sample_to_sample = []
    for i in range(len(sample_feature_vectors)):
        distances = np.linalg.norm(sample_feature_vectors[i] - sample_feature_vectors, axis=1)
        # 将自身与自身的距离设置为无穷大，以便排除
        distances[i] = np.inf
        min_distance = np.min(distances)
        min_distance_list_from_sample_to_sample.append(min_distance)
        print(f"第{i}个特征向量与所有sample_feature_vectors之间的最小距离为:", min_distance)
    d_s_s_maximum=np.max(min_distance_list_from_sample_to_sample)
    d_s_s_median=np.median(min_distance_list_from_sample_to_sample)
    d_s_s_minimum=np.min(min_distance_list_from_sample_to_sample)


    # =========================创新性指标====================================
    # 计算 sample_feature_vectors 每个向量距离dead_feature_vectors所有向量的最小距离，形成列表，以评估生成结果的创新性
    min_distance_list_from_sample_to_dead = []
    for i in range(len(sample_feature_vectors)):
        distances = np.linalg.norm(sample_feature_vectors[i] - dead_feature_vectors, axis=1)
        min_distance = np.min(distances)
        min_distance_list_from_sample_to_dead.append(min_distance)
        print(f"第{i}个特征向量与所有dead_feature_vectors之间的最小距离为:", min_distance)

    d_s_d_maximum=np.max(min_distance_list_from_sample_to_dead)
    d_s_d_median=np.median(min_distance_list_from_sample_to_dead)
    d_s_d_minimum=np.min(min_distance_list_from_sample_to_dead)

    # =========================准确性指标====================================
    ballistic_npz_file = np.load(f"{project_path}/internal_ballistic.npz")
    r2_clustered_best=np.max(ballistic_npz_file['r2_list'])

    npz_file = np.load(f"{project_path}/analysis/all_r2_list.npz")
    r2_sample_median=np.median(npz_file['all_r2_list'])
    r2_sample_minimum=np.min(npz_file['all_r2_list'])

    # =======================聚类结果逐个呈现====================================
    r2_list=ballistic_npz_file['r2_list']
    
    cluster_npz_file = np.load(f"{project_path}/Samples_clustered.npz")
    R_list=cluster_npz_file['R']
    rb_list=cluster_npz_file['r_ref']
    eta_list=cluster_npz_file['loading_fraction_list']

    png_files=[]
    L_list=[]
    for i in range(control_params["cluster_num"]):
        png_file = [f for f in os.listdir(project_path) if f.startswith(f"{i}#") and f.endswith(".png")][0]
        png_files.append(png_file)

        match = re.search(r'L(\d+)', png_file)
        L_value = int(match.group(1))*0.001*R_list[i]
        L_list.append(L_value)
    
    umap_embedding=cluster_npz_file["umap_embedding"]


    # ================生成分析报告并保存为 md 文件============================
    markdown_report_path = f"{project_path}/analysis/analysis_report.md"
    with open(markdown_report_path, 'w') as md_file:
        md_file.write("### 分析报告\n\n")
        md_file.write("- **多样性指标**\n")
        md_file.write("  - 描述: Sample-Sample最小距离列表的统计量\n")
        md_file.write(f"  - 最大值: {d_s_s_maximum}\n")
        md_file.write(f"  - 中值: {d_s_s_median}\n")
        md_file.write(f"  - 最小值: {d_s_s_minimum}\n\n")
        
        md_file.write("- **创新性指标**\n")
        md_file.write("  - 描述: Sample-Data最小距离列表的统计量\n")
        md_file.write(f"  - 最大值: {d_s_d_maximum}\n")
        md_file.write(f"  - 中值: {d_s_d_median}\n")
        md_file.write(f"  - 最小值: {d_s_d_minimum}\n\n")
        
        md_file.write("- **准确性指标**\n")
        md_file.write("  - 描述: Sample的r2统计量\n")
        md_file.write(f"  - 最大值: {r2_clustered_best}\n")
        md_file.write(f"  - 中值: {r2_sample_median}\n")
        md_file.write(f"  - 最小值: {r2_sample_minimum}\n")

        # 结果展示部分
        md_file.write("### 聚类结果展示\n\n")
        for idx, png_file in enumerate(png_files):
            md_file.write(f"#### 第 {idx+1} 个聚类\n")
            md_file.write(f"见:(../{png_file})\n")
            formatted_L = "{0:.4g}".format(L_list[idx]*1000)
            md_file.write(f"L= {formatted_L} mm\n")
            formatted_R = "{0:.3g}".format(R_list[idx]*1000)
            md_file.write(f"R= {formatted_R} mm\n")
            formatted_rb="{0:.3g}".format(rb_list[idx]*1000)
            md_file.write(f"rb= {formatted_rb} mm/s\n")
            formatted_r2="{0:.4g}".format(r2_list[idx])
            md_file.write(f"r2= {formatted_r2}\n")
            formatted_eta = "{0:.3g}".format(eta_list[idx]*100)
            md_file.write(f"eta= {formatted_eta} %\n\n")

        md_file.write("### UMAP向量\n\n")
        md_file.write(str(umap_embedding))

    print(f"Markdown格式的分析报告已保存至 {markdown_report_path}")

    # 将 min_distance_list_from_sample_to_sample 输出为 CSV 文件
    csv_file_path = f"{project_path}/analysis/min_distance_list_from_sample_to_sample.csv"
    with open(csv_file_path, 'w') as csv_file:
        csv_file.write("min_distance\n")
        for distance in min_distance_list_from_sample_to_sample:
            csv_file.write(f"{distance}\n")

    print(f"最小距离列表已保存至 {csv_file_path}")

    # 将 min_distance_list_from_sample_to_dead 输出为 CSV 文件
    csv_file_path = f"{project_path}/analysis/min_distance_list_from_sample_to_dead.csv"
    with open(csv_file_path, 'w') as csv_file:
        csv_file.write("min_distance\n")
        for distance in min_distance_list_from_sample_to_dead:
            csv_file.write(f"{distance}\n")

    print(f"最小距离列表已保存至 {csv_file_path}")

if __name__ == '__main__':
    control_params=get_control_params(question_name="A恒面装药",
        postfix="_epoch50000",
        cluster_num=5,
        guid_w=0.3)
    start_analysis(control_params)